package service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.search.WildcardQuery;

import play.Play;
import play.modules.search.Search;
import service.bingosearch.IndexManager;


import models.Offer;
import models.Service;
import models.User;

public class SearchManager {

	private String[] SplitText(String text){
		return text.trim().toLowerCase().split("\\s+");
	}
	
	public List<Service> SearchServices(String serviceText, List<Long> excludedUsers, Boolean isOffer) throws IOException{		IndexManager indexManager = new IndexManager();
		int hitsPerPage = 10;
		IndexReader reader = IndexReader.open(indexManager.GetIndex("service"));
		
		IndexSearcher searcher = new IndexSearcher(reader);
		TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
		
		BooleanQuery mainQuery = new BooleanQuery();
		String[] termsStr = SplitText(serviceText);

		for (String singleTermStr : termsStr) {
			//title
			Term term = new Term("title",singleTermStr + "*");
			WildcardQuery qTitle = new WildcardQuery(term); 
			//org.apache.lucene.search.Query qTitle = new TermQuery(term);
			qTitle.setBoost(2f);
			mainQuery.add(qTitle,Occur.SHOULD);
			
			//description
			Term termDesc = new Term("description",singleTermStr + "*");
			//Query qDesc = new TermQuery(termDesc);
			WildcardQuery qDesc = new WildcardQuery(termDesc); 
			mainQuery.add(qDesc, Occur.SHOULD);
		}

		//Exclude some users
		for (Long userID : excludedUsers) {
			if (excludedUsers != null){
				Term ownerID = new Term("owner.id",userID.toString());
				TermQuery qOwner = new TermQuery(ownerID);
				mainQuery.add(qOwner,Occur.MUST_NOT);
			}
		}
		
		//Exclude offers/requests
		if (isOffer != null){
			String str = isOffer ? "1" : "0";
			Term t = new Term("isoffer",str);
			TermQuery qIsOffer = new TermQuery(t);
			mainQuery.add(qIsOffer,Occur.MUST);
		}
		
		searcher.search(mainQuery, collector);
		TopDocs topDocs = collector.topDocs();
		ScoreDoc[] hits = topDocs.scoreDocs;
		
		List<Service> services = new ArrayList<Service>();
		for (ScoreDoc scoreDoc : hits) {
			int doc = scoreDoc.doc;
			
			//Title
			String title = searcher.doc(doc).getField("title").stringValue();
			String strID = searcher.doc(doc).getField("id").stringValue();
			Service service = new Offer();
			service.id = Long.parseLong(strID) ;
			service.Relevancy = scoreDoc.score;
			service.title = title;
			service.owner = new User();
			service.owner.fullname = searcher.doc(doc).getField("owner.fullname").stringValue();
			service.IsOffer = searcher.doc(doc).getField("isoffer").stringValue().equals("1");
			
			services.add(service);
		}
		return services;
	}
	
	public List<Service> SearchServices(String serviceText, List<Long> excludedUsers) throws IOException{
		return SearchServices(serviceText,excludedUsers,null);
	}
	
}
